
////////////////////////////////////////////////////////////////////////////
//	File Name: tvmm.h		Last modification at : 2002-10-10 13:50:25
//	Copyright 1999-2002 Microsoft Corporation. All Rights Reserved.
//
//	Author:      Rong Xiao
//	Email :      t-rxiao@microsoft.com
//
//	Description : 
//
//	Revision History: 
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __TVMM_H__
#define __TVMM_H__

#include "tmatrix.h"

template <class T>
class TVMMap {
protected:
	T* m_data;
	HANDLE m_hFile;
	unsigned int m_nSize;
	unsigned int m_nByteSizeMax;
	
public:
	bool CreateVMMFile( char* pszMapFileName, unsigned int nByteSizeMax );
	bool CloseVMMFile(void);
	T* Allocate(char* pszMappingObjectName, unsigned int nSize);
	bool Free();
	bool Flush(T* ptr,  unsigned int nElement);
	TVMMap() : m_data(0), m_hFile(0) {};
	~TVMMap() { Free(); CloseVMMFile(); }
};

template <class T>
T* TVMMap<T>::Allocate(char* pszMappingObjectName, unsigned int nSize) 
{
	unsigned int nLen;

	nLen=nSize*sizeof(T);

	if (  nLen > m_nByteSizeMax ) {
		AfxMessageBox("Cache file overflow\n");
		return 0;
	}

	HANDLE hMapFile;
	hMapFile = CreateFileMapping(m_hFile,    // Current file handle. 
				NULL,                              // Default security. 
				PAGE_READWRITE,                    // Read/write permission. 
				0,                                 // Max. object size. 
				nLen,                                 // Size of hFile. 
				pszMappingObjectName);            // Name of mapping object. 
 	if (!hMapFile)	{
		AfxMessageBox("Unable to open shared file\n");
		return FALSE;
	}
	m_data = (T* ) MapViewOfFile((HANDLE) hMapFile,
		FILE_MAP_ALL_ACCESS,
		0, 
		0,
		0);

	if (!m_data)	{
		AfxMessageBox("Unable to map view of a file");
	}

	return m_data;
}

template <class T>
bool  TVMMap<T>::Free()
{
	assert(m_data);

	if (!::UnmapViewOfFile(m_data))	{
		AfxMessageBox("Unable to Unmap View");
		return false;
	}


	return true;
} 


template <class T>
bool TVMMap<T>::Flush( T* ptr,  unsigned int  nElement)
{
	if ( !ptr || ptr<m_data || (ptr+nElement)>(m_data+m_nSize) )
		return false;

	unsigned int nSize;
	nSize=nElement*sizeof(T);

	FlushViewOfFile(ptr, nSize);
	return true;
}


template <class T>
bool  TVMMap<T>::CreateVMMFile( char* pszMapFileName, unsigned int nByteSizeMax )
{

	m_nByteSizeMax=nByteSizeMax;
	m_hFile = CreateFile(pszMapFileName,           // open MYFILE.TXT 
				GENERIC_READ | GENERIC_WRITE,      // open for reading and write 
                FILE_SHARE_READ,           // share for reading 
                NULL,                      // no security 
                CREATE_ALWAYS,             // create new file 
                FILE_ATTRIBUTE_NORMAL,     // normal file 
                NULL);                     // no attr. template 
	
	assert ( INVALID_HANDLE_VALUE!=m_hFile );
	if ( !m_hFile ) 
		return false;

	int* tmpBuf;
	unsigned long nLoop, nWrite;
	const int nBufLen=2048*sizeof(int);
	tmpBuf=new int[2048];

	TArrayInit(tmpBuf,2048);
	nLoop=nByteSizeMax/nBufLen ;

	for ( unsigned long i=0; i<=nLoop; i++ )
		WriteFile(m_hFile,tmpBuf,nBufLen,&nWrite,0);

	SetFilePointer(m_hFile, 0, 0, FILE_BEGIN );

	delete[] tmpBuf;
	return true;
} 

template <class T>
bool  TVMMap<T>::CloseVMMFile(void) 
{	
	CloseHandle((HANDLE)m_hFile);  
	m_hFile = 0; 
	return true;
}

namespace FAST
{

template <class T>
class TVMM_Matrix : public TMatrix<T>
{
protected:
	TVMMap<T>	m_vmmaper;
public:
	inline T* NewSize(char* pszMapFileName, char* pszMappingObjectName,
		const int rows, const int cols);
	~TVMM_Matrix() {}	
};

template <class T>
T* TVMM_Matrix<T>::NewSize(char* pszMapFileName, char* pszMappingObjectName,
		const int rows, const int cols)
{
	initSize(rows,cols);

	unsigned int nLen;
	nLen=m_cbSize*sizeof(T);
	m_vmmaper.CreateVMMFile(pszMapFileName, nLen);
    m_data=m_vmmaper.Allocate(pszMappingObjectName, m_cbSize);
	return m_data;
}

} //end of namespace
#endif